二、索引类型
Mysql目前主要有以下几种索引类型：FULLTEXT，HASH，BTREE，RTREE。

1. FULLTEXT
即为全文索引，目前只有MyISAM引擎支持。其可以在CREATE TABLE ，ALTER TABLE ，CREATE INDEX 使用，不过目前只有 CHAR、VARCHAR ，TEXT 列上可以创建全文索引。

全文索引并不是和MyISAM一起诞生的，它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。

2. HASH
由于HASH的唯一（几乎100%的唯一）及类似键值对的形式，很适合作为索引。

HASH索引可以一次定位，不需要像树形索引那样逐层查找,因此具有极高的效率。但是，这种高效是有条件的，即只在“=”和“in”条件下高效，对于范围查询、排序及组合索引仍然效率不高。

3. BTREE
BTREE索引就是一种将索引值按一定的算法，存入一个树形的数据结构中（二叉树），每次查询都是从树的入口root开始，依次遍历node，获取leaf。这是MySQL里默认和最常用的索引类型。

4. RTREE
RTREE在MySQL很少使用，仅支持geometry数据类型，支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。

相对于BTREE，RTREE的优势在于范围查找。

ps. 此段详细内容见此片博文：Mysql几种索引类型的区别及适用情况

三、索引种类
普通索引：仅加速查询

唯一索引：加速查询 + 列值唯一（可以有null）

主键索引：加速查询 + 列值唯一（不可以有null）+ 表中只有一个

组合索引：多列值组成一个索引，专门用于组合搜索，其效率大于索引合并

全文索引：对文本的内容进行分词，进行搜索

ps.

索引合并，使用多个单列索引组合搜索
覆盖索引，select的数据列只用从索引中就能够取得，不必读取数据行，换句话说查询列要被所建的索引覆盖


创建索引
复制代码
1

--创建普通索引CREATE INDEX index_name ON table_name(col_name);
--创建唯一索引CREATE UNIQUE INDEX index_name ON table_name(col_name);
--创建普通组合索引CREATE INDEX index_name ON table_name(col_name_1,col_name_2);
--创建唯一组合索引CREATE UNIQUE INDEX index_name ON table_name(col_name_1,col_name_2);

复制代码
2. 通过修改表结构创建索引
1

ALTER TABLE table_name ADD INDEX index_name(col_name);

3. 创建表时直接指定索引
复制代码


CREATE TABLE table_name (

ID INT NOT NULL,
col_name VARCHAR (16) NOT NULL,
INDEX index_name (col_name)

);

复制代码
4. 删除索引


--直接删除索引DROP INDEX index_name ON table_name;
--修改表结构删除索引ALTER TABLE table_name DROP INDEX index_name;

5. 其它相关命令
复制代码



- 查看表结构

desc table_name;

- 查看生成表的SQL

show create table table_name;

- 查看索引

show index from  table_name;

- 查看执行时间

set profiling = 1;

SQL...

show profiles;

复制代码
五、创建索引的时机
到这里我们已经学会了建立索引，那么我们需要在什么情况下建立索引呢？一般来说，在WHERE和JOIN中出现的列需要建立索引，但也不完全如此，因为MySQL只对<，<=，=，>，>=，BETWEEN，IN，以及某些时候的LIKE才会使用索引。例如：

1

SELECT t.Name  FROM mytable_t LEFT JOIN mytable_m ON t.Name=m.username WHERE m.age=20 AND m.city='郑州' ;

此时就需要对city和age建立索引，由于mytable_m表的userame也出现在了JOIN子句中，也有对它建立索引的必要。

刚才提到只有某些时候的LIKE才需建立索引。因为在以通配符%和_开头作查询时，MySQL不会使用索引。

六、命中索引
数据库表中添加索引后确实会让查询速度起飞，但前提必须是正确的使用索引来查询，如果以错误的方式使用，则即使建立索引也会不奏效。
即使建立索引，索引也不会生效：

复制代码


- like '%xx'    select * from tb1 where name like '%cn';- 使用函数

select * from tb1 where reverse(name) = 'wupeiqi';- or    select * from tb1 where nid = 1 or email = 'seven@live.com';

特别的：当or条件中有未建立索引的列才失效，以下会走索引

select * from tb1 where nid = 1 or name = 'seven';

select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'- 类型不一致

如果列是字符串类型，传入条件是必须用引号引起来，不然...

select * from tb1 where name = 999;- !=    select * from tb1 where name != 'alex'    特别的：如果是主键，则还是会走索引

select * from tb1 where nid != 123- >    select * from tb1 where name > 'alex'    特别的：如果是主键或索引是整数类型，则还是会走索引

select * from tb1 where nid > 123        select * from tb1 where num > 123- order by    select email from tb1 order by name desc;

当根据索引排序时候，选择的映射如果不是索引，则不走索引

特别的：如果对主键排序，则还是走索引：

select * from tb1 order by nid desc;

- 组合索引最左前缀

如果组合索引为：(name,email)

name and email       -- 使用索引    name                 -- 使用索引    email                -- 不使用索引

复制代码
七、其它注意事项
复制代码
1

- 避免使用select *- count(1)或count(列) 代替 count(*)- 创建表时尽量时 char 代替 varchar- 表的字段顺序固定长度的字段优先- 组合索引代替多个单列索引（经常使用多个条件查询时）- 尽量使用短索引- 使用连接（JOIN）来代替子查询(Sub-Queries)- 连表时注意条件类型需一致- 索引散列值（重复多）不适合建索引，例：性别不适合

复制代码
八、LIMIT分页
若需求是每页显示10条数据，如何建立分页？

我们可以先使用LIMIT尝试：

1

--第一页SELECT * FROM table_name LIMIT 0,10;--第二页SELECT * FROM table_name LIMIT 10,10;--第三页SELECT * FROM table_name LIMIT 20,10;

但是这样做有如下弊端：

每一条select语句都会从1遍历至当前位置，若跳转到第100页，则会遍历1000条记录

若记录的id不连续，则会出错

改善：

若已知每页的max_id和min_id，则可以通过主键索引来快速定位:

复制代码
1

--下一页SELECT * FROM table_name WHERE id in (SELECT id FROM table_name WHERE id > max_id LIMIT 10);--上一页SELECT * FROM table_name WHERE id in (SELECT id FROM table_name WHERE id < min_id ORDER BY id DESC LIMIT 10);--当前页之后的某一页SELECT * FROM table_name WHERE id in (SELECT id FROM (SELECT id FROM (SELECT id FROM table_name WHERE id < min_id ORDER BY id desc LIMIT (页数差*10)) AS N ORDER BY N.id ASC LIMIT 10) AS P ORDER BY P.id ASC);--当前页之前的某一页SELECT * FROM table_name WHERE id in (SELECT id FROM (SELECT id FROM (SELECT id FROM table_name WHERE id > max_id LIMIT (页数差*10)) AS N ORDER BY N.id DESC LIMIT 10) AS P) ORDER BY id ASC;

复制代码
九、执行计划
explain + 查询SQL - 用于显示SQL执行信息参数，根据参考信息可以进行SQL优化

复制代码
1

mysql> explain select * from tb2;+----+-------------+-------+------+---------------+------+---------+------+------+-------+| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------+|  1 | SIMPLE      | tb2   | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |+----+-------------+-------+------+---------------+------+---------+------+------+-------+1 row in set (0.00 sec)

复制代码
上表详解
十、慢查询日志
MySQL的慢查询日志是MySQL提供的一种日志记录，它用来记录在MySQL中响应时间超过阀值的语句，具体指运行时间超过long_query_time值的SQL，则会被记录到慢查询日志中。long_query_time的默认值为10，意思是运行10S以上的语句。默认情况下，MySQLl数据库并不启动慢查询日志，需要我们手动来设置这个参数，当然，如果不是调优需要的话，一般不建议启动该参数，因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件，也支持将日志记录写入数据库表。

1. 查看慢日志参数：
复制代码
1

--查询配置命令show variables like '%query%';--当前配置参数binlog_rows_query_log_events    OFFft_query_expansion_limit    20have_query_cache    YES--时间限制，超过此时间，则记录long_query_time    10.000000query_alloc_block_size    8192query_cache_limit    1048576query_cache_min_res_unit    4096query_cache_size    1048576query_cache_type    OFFquery_cache_wlock_invalidate    OFFquery_prealloc_size    8192--是否开启慢日志记录slow_query_log    OFF--日志文件slow_query_log_file    D:\Program Files (x86)\mysql-5.7.18-winx64\data\Jack-slow.log--

复制代码
2. 修改当前配置
1

set global 变量名 = 值;--例如，修改时间限制为20slong_query_time = 20;

ps.也可以直接打开慢日志配置文件进行修改，但必须重启服务才能生效

3. 查看MySQL慢日志
1

mysqldumpslow -s at -a  /usr/local/var/mysql/MacBook-Pro-3-slow.log



复制代码


"""--verbose    版本--debug      调试--help       帮助 -v           版本-d           调试模式-s ORDER     排序方式

what to sort by (al, at, ar, c, l, r, t), 'at' is default              al: average lock time

ar: average rows sent

at: average query time

c: count               l: lock time

r: rows sent

t: query time-r           反转顺序，默认文件倒序拍。reverse the sort order (largest last instead of first)-t NUM       显示前N条just show the top n queries-a           不要将SQL中数字转换成N，字符串转换成S。don't abstract all numbers to N and strings to 'S'-n NUM       abstract numbers with at least n digits within names

-g PATTERN   正则匹配；grep: only consider stmts that include this string

-h HOSTNAME  mysql机器名或者IP；hostname of db server for *-slow.log filename (can be wildcard),

default is '*', i.e. match all

-i NAME      name of server instance (if using mysql.server startup script)

-l           总时间中不减去锁定时间；don't subtract lock time from total time

"""


<?php

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/8/23
 * Time: 13:42
 */
class 索引
{

}